[AWS CDK] readonly として公開された Construct クラスのプロパティに対して、他のクラス内で grant メソッドを使えるのか確認してみた

[AWS CDK] readonly として公開された Construct クラスのプロパティに対して、他のクラス内で grant メソッドを使えるのか確認してみた

結論: grant メソッドにより更新されるのはリソースを使う側の実行ロールであるため問題なく使えました。 by 若槻
Clock Icon2024.07.22

こんにちは、製造ビジネステクノロジー部の若槻です。

AWS CDKでは、リソースを異なる Construct クラスに論理分割して作成し、クラスのプロパティにより Construct 間で共有することができます。

その際にプロパティの公開を readonly で行うことができます。例えば下記では StringParameter のオブジェクトに対応する myParameter プロパティを readonly で公開しています。これにより、クラスの外ではプロパティが変更不可であることを明示することができます。

export class ParametersConstruct extends Construct {
  public readonly myParameter: aws_ssm.StringParameter; // readonly で外部から myParameter オブジェクトを変更できないようにする
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const myParameter = new aws_ssm.StringParameter(this, 'MyParameter', {
      parameterName: '/my-parameter',
      stringValue: 'my-value',
    });

    this.myParameter = myParameter;
  }
}

ここで、readonly として公開された Construct クラスのプロパティに対して、他のクラス内で grant メソッドを使えるのか?気になったので確認してみました。

確認してみた

AWS CDK における grant メソッドを使うことにより、Lambda 関数からパラメーターストアに対する読み取りや書き込みの権限の付与を抽象的に行うことが可能となります。

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/permissions.html

それでは下記のように、ParametersConstruct クラスで readonly として公開された myParameter プロパティのオブジェクトに対して、grantRead メソッドを使えるのか確認してみます。

lib/cdk-sample-stack.ts
import { aws_ssm, aws_lambda_nodejs, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class ParametersConstruct extends Construct {
  public readonly myParameter: aws_ssm.StringParameter; // readonly で外部から myParameter オブジェクトを変更できないようにする
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const myParameter = new aws_ssm.StringParameter(this, 'MyParameter', {
      parameterName: '/my-parameter',
      stringValue: 'my-value',
    });

    this.myParameter = myParameter;
  }
}

export class LambdaConstruct extends Construct {
  constructor(
    scope: Construct,
    id: string,
    props: {
      myParameter: aws_ssm.StringParameter;
    }
  ) {
    super(scope, id);

    const { myParameter } = props;

    const sampleFunc = new aws_lambda_nodejs.NodejsFunction(
      this,
      'SampleFunc',
      {}
    );

    myParameter.grantRead(sampleFunc); // sampleFunc から myParameter に対する読み取り権限を付与できる?
  }
}

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const parameters = new ParametersConstruct(this, 'ParametersConstruct');

    new LambdaConstruct(this, 'LambdaConstruct', parameters);
  }
}

結論として、上記の実装に対して CDK デプロイを問題なく行うことができました。

$ npm run deploy

> cdk_sample_app@0.1.0 deploy
> cdk deploy --require-approval never --method=direct

Bundling asset CdkSampleStack/LambdaConstruct/SampleFunc/Code/Stage...

  cdk.out/bundling-temp-29469e2f40d97db89f9e6a43f35c62b1528b60fca11b1b7e4033a3aed17313b4/index.js  1.2kb

⚡ Done in 13ms
[Warning at /CdkSampleStack/LambdaConstruct] Be aware that the NodeJS runtime of Node 16 will be deprecated by Lambda on June 12, 2024. Lambda runtimes Node 18 and higher include SDKv3 and not SDKv2. Updating your Lambda runtime will require bundling the SDK, or updating all SDK calls in your handler code to use SDKv3 (which is not a trivial update). Please account for this added complexity and update as soon as possible. [ack: aws-cdk-lib/aws-lambda-nodejs:runtimeUpdateSdkV2Breakage]

✨  Synthesis time: 4.88s

CdkSampleStack:  start: Building f9ea4ac76a287dd339aae1744e12273578a934e6c9f421b1602ddd2b7c0e505f:current_account-current_region
CdkSampleStack:  success: Built f9ea4ac76a287dd339aae1744e12273578a934e6c9f421b1602ddd2b7c0e505f:current_account-current_region
CdkSampleStack:  start: Publishing f9ea4ac76a287dd339aae1744e12273578a934e6c9f421b1602ddd2b7c0e505f:current_account-current_region
CdkSampleStack:  start: Building 008866f27569e82b4c9822b588b692aa7a52ba566962332d6c2a3467719c223c:current_account-current_region
CdkSampleStack:  success: Built 008866f27569e82b4c9822b588b692aa7a52ba566962332d6c2a3467719c223c:current_account-current_region
CdkSampleStack:  start: Publishing 008866f27569e82b4c9822b588b692aa7a52ba566962332d6c2a3467719c223c:current_account-current_region
CdkSampleStack:  success: Published 008866f27569e82b4c9822b588b692aa7a52ba566962332d6c2a3467719c223c:current_account-current_region
CdkSampleStack:  success: Published f9ea4ac76a287dd339aae1744e12273578a934e6c9f421b1602ddd2b7c0e505f:current_account-current_region
CdkSampleStack: deploying... [1/1]
CdkSampleStack: updating stack...

 ✅  CdkSampleStack

✨  Deployment time: 73.09s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/CdkSampleStack/bdcdf7a0-3443-11ef-8401-06d40bdb5af9

✨  Total time: 77.97s

grant は実行ロールを更新するメソッドなので使えて当然だった

ここで grantRead を行う場合と行わない場合とで CDK Diff を実行してみると、差分が発生しているのは Lambda 関数の実行ロールに対してのみでした。

$ npx cdk diff
Bundling asset CdkSampleStack/LambdaConstruct/SampleFunc/Code/Stage...

  cdk.out/bundling-temp-29469e2f40d97db89f9e6a43f35c62b1528b60fca11b1b7e4033a3aed17313b4/index.js  1.2kb

⚡ Done in 7ms
[Warning at /CdkSampleStack/LambdaConstruct] Be aware that the NodeJS runtime of Node 16 will be deprecated by Lambda on June 12, 2024. Lambda runtimes Node 18 and higher include SDKv3 and not SDKv2. Updating your Lambda runtime will require bundling the SDK, or updating all SDK calls in your handler code to use SDKv3 (which is not a trivial update). Please account for this added complexity and update as soon as possible. [ack: aws-cdk-lib/aws-lambda-nodejs:runtimeUpdateSdkV2Breakage]
Stack CdkSampleStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
IAM Statement Changes
┌───┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┬────────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────┬───────────┐
│   │ Resource                                                                                                      │ Effect │ Action                                                                         │ Principal                                     │ Condition │
├───┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────┼───────────┤
│ + │ arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${ParametersConstructMyParameter8847876B} │ Allow  │ ssm:DescribeParameters                                                         │ AWS:${LambdaConstruct/SampleFunc/ServiceRole} │           │
│   │                                                                                                               │        │ ssm:GetParameter                                                               │                                               │           │
│   │                                                                                                               │        │ ssm:GetParameterHistory                                                        │                                               │           │
│   │                                                                                                               │        │ ssm:GetParameters                                                              │                                               │           │
└───┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┴────────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────┴───────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Resources
[+] AWS::IAM::Policy LambdaConstruct/SampleFunc/ServiceRole/DefaultPolicy LambdaConstructSampleFuncServiceRoleDefaultPolicy50342B38 
[~] AWS::Lambda::Function LambdaConstruct/SampleFunc LambdaConstructSampleFunc3DFB80E5 
 └─ [~] DependsOn
     └─ @@ -1,3 +1,4 @@
        [ ] [
        [-]   "LambdaConstructSampleFuncServiceRole1013E974"
        [+]   "LambdaConstructSampleFuncServiceRole1013E974",
        [+]   "LambdaConstructSampleFuncServiceRoleDefaultPolicy50342B38"
        [ ] ]

✨  Number of stacks with differences: 1

よって readonly として公開された myParameter に対する変更は行われなかったので問題にはならないことが分かりました。

おわりに

AWS CDK で readonly として公開された Construct クラスのプロパティに対して、他のクラス内で grant メソッドを使えるのか確認してみました。

結論としては grant メソッドにより実際に更新されるのはリソースに"アクセスする側"の実行ロールであるため、readonly として公開されたプロパティに対しても問題なく使用することができるという、考えてみれば当然の結果となりました。

ネクストアクション

本ブログを書いている間に、実際にリソースの変更を行う addGlobalSecondaryIndex や、L1 レイヤーで変更を加えた場合はどうなのか気になったので、次回以降で試してみたいと思います。

以上

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.